/* 
 * FilePrinter.java 07.05.2011
 *  
 *  
 * Candidate: Alessandra Otterbach
 * Prometric ID: Algisina1
 * Username: Algisina
 *  
 * Sun Certified Developer for Java 2 Platform, Standard Edition Programming 
 * Assignment (CX-310-252A)
 *  
 * This class is part of the Programming Assignment of the Sun Certified 
 * Developer for Java 2 Platform, Standard Edition certification program, must 
 * not be used out of this context and must be used exclusively by Sun 
 * Microsystems, Inc. 
 */
package suncertify.db;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Map;

import suncertify.db.exc.RecordNotFoundException;
import suncertify.util.SearchCriteriaConverter;

/**
 * @author Alessandra Otterbach
 * 
 */
public class FileReader {

    /** Character Encoding */
    private static final String ENCODING = "US-ASCII";
    /** The value that identifies a record as being valid */
    private static final int VALID = 0;
    /** The bytes that store the length of each field name */
    private static final int FIELD_NAME_BYTES = 2;
    /** The bytes that store the fields length */
    private static final int FIELD_LENGTH_BYTES = 2;

    private static int HEADER;

    private static int LENGTH;

    public static Map<Integer, String[]> readDatas(String databaseLocation)
	    throws IOException {
	Map<Integer, String[]> roomMap = new HashMap<Integer, String[]>();
	File file = new File(databaseLocation);
	RandomAccessFile raf = new RandomAccessFile(file, "r");

	int magicCookie = raf.readInt();
	System.out.println("Magic Cookie: " + magicCookie);

	LENGTH = raf.readInt();
	System.out.println("Length: " + LENGTH);

	short numberFields = raf.readShort();
	System.out.println("Number of Fields: " + numberFields);

	String[] fieldNames = new String[numberFields];
	int[] fieldLengths = new int[numberFields];
	for (int i = 0; i < numberFields; i++) {
	    final byte nameLengthByteArray[] = new byte[FIELD_NAME_BYTES];
	    raf.read(nameLengthByteArray);
	    final int nameLength = getValue(nameLengthByteArray);
	    System.out.println("nameLength " + nameLength);

	    final byte[] fieldNameByteArray = new byte[nameLength];
	    raf.read(fieldNameByteArray);
	    fieldNames[i] = new String(fieldNameByteArray, ENCODING);
	    System.out.println("fieldName " + fieldNames[i]);

	    final byte[] fieldLength = new byte[FIELD_LENGTH_BYTES];
	    raf.read(fieldLength);
	    fieldLengths[i] = getValue(fieldLength);
	    System.out.println("fieldLength " + fieldLengths[i]);
	    System.out.println("*************");
	}
	HEADER = (int) raf.getFilePointer();
	for (int i = 1; i <= getRecNos(raf); i++) {
	    String[] roomRecord = new String[7];
	    System.out.println("***************** RECORD NR. " + i
		    + " ***********");

	    // Deleted Flag
	    byte flag = raf.readByte();
	    System.out.println("Deleted Flag: " + flag);

	    // Name
	    byte[] fieldLength = new byte[64];
	    raf.read(fieldLength);
	    String name = new String(fieldLength, ENCODING).trim();
	    System.out.println("Name: " + name);

	    // Location
	    raf.read(fieldLength);
	    String location = new String(fieldLength, ENCODING).trim();
	    System.out.println("Location: " + location);

	    // Size
	    fieldLength = new byte[4];
	    raf.read(fieldLength);
	    String size = new String(fieldLength, ENCODING).trim();
	    System.out.println("Size: " + size);

	    // Smoking
	    fieldLength = new byte[1];
	    raf.read(fieldLength);
	    String smoking = new String(fieldLength, ENCODING).trim();
	    System.out.println("Smoking: " + smoking);

	    // Rate
	    fieldLength = new byte[8];
	    raf.read(fieldLength);
	    String rate = new String(fieldLength, ENCODING).trim();
	    System.out.println("Rate: " + rate);

	    // Date
	    fieldLength = new byte[10];
	    raf.read(fieldLength);
	    String date = new String(fieldLength, ENCODING).trim();
	    System.out.println("Date: " + date);

	    // Owner
	    fieldLength = new byte[8];
	    raf.read(fieldLength);
	    String owner = new String(fieldLength, ENCODING).trim();
	    System.out.println("Owner: " + owner);

	    if (flag == VALID) {
		roomRecord[0] = name;
		roomRecord[1] = location;
		roomRecord[2] = size;
		roomRecord[3] = smoking;
		roomRecord[4] = rate;
		roomRecord[5] = date;
		roomRecord[6] = owner;

		roomMap.put(i, roomRecord);
	    } else {
		roomMap.put(i, null);
	    }
	}
	return roomMap;
    }

    /**
     * Converts to <code>int</code> the content of a given <code>byte</code>
     * array.
     * 
     * @param byteArray
     *            The <code>byte</code> array that contains the number to be
     *            converted.
     * @return An <code>int</code> that represents the content of the
     *         <code>byte</code> array, provided as argument.
     */
    private static int getValue(final byte[] byteArray) {
	int value = 0;
	final int byteArrayLength = byteArray.length;

	for (int i = 0; i < byteArrayLength; i++) {
	    final int shift = (byteArrayLength - 1 - i) * 8;
	    value += (byteArray[i] & 0x000000FF) << shift;
	}

	return value;
    }

    private static int getRecNos(RandomAccessFile raf) throws IOException {
	int numberRecNos;

	// Length of file minus Header (74) divided record length (160)
	numberRecNos = (int) ((raf.length() - HEADER) / LENGTH);

	return numberRecNos;
    }

    public static Map<Integer, String[]> readData(String path)
	    throws IOException, RecordNotFoundException {
	DB data = Data.getInstance(path);

	Map<Integer, String[]> roomMap = new HashMap<Integer, String[]>();
	// Find all recNos
	int[] recNos = data.find(SearchCriteriaConverter
		.searchCriteriaAsArray(null));

	// for each found recNo, read record
	for (int i = 0; i < recNos.length; i++) {
	    String[] recordValues;
	    try {
		recordValues = data.read(recNos[i]);
		roomMap.put(recNos[i], recordValues);
	    } catch (RecordNotFoundException e) {
		roomMap.put(recNos[i], null);
	    }
	}

	return roomMap;
    }

}
